package com.sailing.xjpb.common;

import org.joda.time.DateTime;
import org.joda.time.Days;
import org.joda.time.Years;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;

import static com.sailing.xjpb.common.time.DateFormat.YYYY_MM_DD_HH_MM_SS;

/**
 * Description 业务时间工具类
 *
 * @author YaoWei
 */
public class DateUtils {


    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS);

    private DateUtils() {

    }

    /**
     * Description: sql 查询中日期转为最小的Timestamp
     *
     * @param value 日期
     * @return 当天最小日期
     * @author YaoWei
     */
    public static Date minTimeOfDay(String value) {
        Date date = toDate(value, null);
        if (date == null) {
            return null;
        } else {
            return new DateTime(date).withHourOfDay(0)
                    .withMinuteOfHour(0)
                    .withSecondOfMinute(0)
                    .withMillisOfSecond(0).toDate();
        }
    }

    /**
     * Description: sql 查询中日期转为最大的Timestamp
     *
     * @param value 日期
     * @return 当天最大日期
     * @author YaoWei
     */
    public static Date maxTimeOfDay(String value) {
        Date date = toDate(value, null);
        if (date == null) {
            return null;
        }
        return new DateTime(date).withHourOfDay(23)
                .withMinuteOfHour(59)
                .withSecondOfMinute(59)
                .withMillisOfSecond(999).toDate();
    }


    /**
     * 日期格式对象转换为日期格式
     *
     * @param value       日期格式对象
     * @param defaultDate 为空时默认返回的日期
     * @return 如果日期为空，返回默认日期
     */
    public static Date toDate(Object value, Date defaultDate) {
        Date toDate = toDate(value);
        return toDate != null ? toDate : defaultDate;
    }

    /**
     * 日期格式对象转换为日期格式
     *
     * @param value 日期格式对象
     * @return 转换后的日期
     */
    public static Date toDate(Object value) {
        return TypeUtils.toDate(value);
    }

    /**
     * 判断dateStr1是否小于dateStr2
     *
     * @param dateStr1 日期格式字符串(非空)
     * @param dateStr2 日期格式字符串(非空)
     */
    public static boolean before(String dateStr1, String dateStr2) {
        return compare(dateStr1, dateStr2) < 0;
    }

    /**
     * 判断date1是否小于date2
     *
     * @param date1 日期(非空)
     * @param date2 日期(非空)
     */
    public static boolean before(Date date1, Date date2) {
        return compare(date1, date2) < 0;
    }

    /**
     * 判断dateStr1是否大于dateStr2
     *
     * @param dateStr1 日期格式字符串(非空)
     * @param dateStr2 日期格式字符串(非空)
     */
    public static boolean after(String dateStr1, String dateStr2) {
        return compare(dateStr1, dateStr2) > 0;
    }

    /**
     * 判断date1是否大于date2
     *
     * @param date1 日期(非空)
     * @param date2 日期(非空)
     */
    public static boolean after(Date date1, Date date2) {
        return compare(date1, date2) > 0;
    }

    /**
     * 比较dateStr1与dateStr2
     *
     * @param dateStr1 日期格式字符串(非空)
     * @param dateStr2 日期格式字符串(非空)
     */
    public static int compare(String dateStr1, String dateStr2) {
        SailingAssert.isNotEmpty(dateStr1, "日期字符串不能为空！");
        SailingAssert.isNotEmpty(dateStr2, "日期字符串不能为空！");
        Date dateTime1 = toDate(dateStr1, null);
        Date dateTime2 = toDate(dateStr2, null);
        if (dateTime1 != null) {
            return dateTime1.compareTo(dateTime2);
        }
        return -1;
    }

    /**
     * 比较date1与date2
     *
     * @param date1 日期(非空)
     * @param date2 日期(非空)
     */
    public static int compare(Date date1, Date date2) {
        SailingAssert.notNull(date1, "日期1不能为空！");
        SailingAssert.notNull(date2, "日期2不能为空！");
        return date1.compareTo(date2);
    }

    /**
     * 判断当前日期是否在一个日期区间内
     *
     * @param start   开始日期
     * @param end     结束日期
     * @param current 当前日期
     */
    public static boolean between(Date start, Date end, Date current) {
        if (start == null || end == null || current == null) {
            return false;
        }
        return start.compareTo(current) <= 0 && end.compareTo(current) >= 0;
    }

    /**
     * 由出生日期获得年龄
     *
     * @param birthDay 出生日期
     * @return 生日
     * @author 付玉龙
     */
    public static int getAge(Date birthDay) {
        DateTime birthdayDateTime = new DateTime(birthDay);
        Years age = Years.yearsBetween(birthdayDateTime, new DateTime());
        return age.getYears();
    }

    /**
     * 计算两个日期相差的天数
     *
     * @param time1 时间1
     * @param time2 时间2
     * @return long 相差天数
     */
    public static int getDays(String time1, String time2) {
        Date dateTime1 = toDate(time1, new Date());
        Date dateTime2 = toDate(time2, new Date());
        Days days = Days.daysBetween(new DateTime(dateTime1), new DateTime(dateTime2));
        return days.getDays();
    }

    /**
     * 判断两个日期是否相等
     *
     * @param d1 日期1
     * @param d2 日期2
     * @return true相等 | false不相等
     */
    public static boolean equals(Date d1, Date d2) {
        return d1 == d2 || d1.compareTo(d2) == 0;
    }

    /**
     * 日期转字符串
     *
     * @param date   日期
     * @param format 格式化
     * @return 格式化后的日期字符串
     */
    public static String toString(Date date, String format) {
        if (date == null) {
            return null;
        }
        return new DateTime(date).toString(format);
    }

    /**
     * 日期转SailingConstants.DEFAULT_DATE_FORMAT字符串
     *
     * @param date 日期
     * @return 格式化后的日期字符串
     */
    public static String toString(Date date) {
        return toString(date, SailingConstants.DEFAULT_DATE_FORMAT);
    }

    /**
     * add by luozy since 20230223
     **/
    public static LocalDateTime toLocalDateTime(String dateTimeStr) {
        return LocalDateTime.parse(dateTimeStr, formatter);
    }

    public static String toString(LocalDateTime dateTime) {
        return dateTime.format(formatter);
    }

    public static String toString(LocalDateTime dateTime, String customFormatterString) {
        return dateTime.format(DateTimeFormatter.ofPattern(customFormatterString));
    }

    public static String toString(LocalDateTime dateTime, DateTimeFormatter customFormatter) {
        return dateTime.format(customFormatter);
    }

    public static Date toDate(LocalDateTime dateTime) {
        return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static LocalDateTime toLocalDateTime(Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }

    public static long toTimestamp(LocalDateTime dateTime) {
        return dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    public static LocalDateTime fromTimestamp(long timestamp) {
        return LocalDateTime.ofInstant(new Date(timestamp).toInstant(), ZoneId.systemDefault());
    }

    /**
     * 比较两个时间 Duration.toDays  天数差  Duration.toHours 小时差 等
     *
     * @param beginTime 开始时间
     * @param endTime   结束时间
     * @return Duration
     */
    public static Duration getDuration(LocalDateTime beginTime, LocalDateTime endTime) {
        return Duration.between(beginTime, endTime);
    }

}
